package com.ttxz.common.base.viewmodel

import androidx.lifecycle.*
import com.ttxz.common.base.model.BaseModel
import com.kunminx.architecture.ui.callback.UnPeekLiveData
import com.ttxz.common.http.HttpResponse
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.onCompletion
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
import org.joor.Reflect
import java.lang.reflect.ParameterizedType

/**
 * 简要说明
 *
 * @author ttxz
 * @date 2022/6/10 15:37
 */
open class BaseViewModel<out M : BaseModel> : ViewModel(), DefaultLifecycleObserver {
    /**
     * 显示loading框的事件
     */
    var showLoadingEvent: UnPeekLiveData<Boolean> = UnPeekLiveData.Builder<Boolean>().create()

    /**
     * 显示Toast提示的事件
     */
    var showToastEvent: UnPeekLiveData<String> = UnPeekLiveData.Builder<String>().create()

    /**
     * 界面跳转事件
     */
    var switchActivityEvent: UnPeekLiveData<Class<*>> = UnPeekLiveData.Builder<Class<*>>().create()
    lateinit var  model: @UnsafeVariance M

    /**
     * ViewModel创建完成的生命周期方法监听，用于执行自身的业务处理
     */
    fun initData() {
        val viewClass: Class<*>
        val type = javaClass.genericSuperclass
        if (type is ParameterizedType) {
            viewClass = type.actualTypeArguments[0] as Class<*>
            model = Reflect.onClass(viewClass).create().get()
        }
    }

    fun showLoadingDialog() {
        showLoadingEvent.postValue(true)
    }

    fun dismissLoadingDialog() {
        showLoadingEvent.postValue(false)
    }

    fun showToast(str: String) {
        showToastEvent.postValue(str)
    }

    fun switchActivity(clazz: Class<*>) {
        switchActivityEvent.postValue(clazz)
    }

    override fun onDestroy(owner: LifecycleOwner) {
        super.onDestroy(owner)
        //当界面关闭后，此方法用来销毁资源
    }

    protected fun <T> launchWithLoading(
            requestBlock: suspend () -> HttpResponse<T>?,
            resultCallback: (HttpResponse<T>?) -> Unit
    ) {
        viewModelScope.launch {
            flow {
                emit(requestBlock.invoke())
            }.onStart {
                showLoadingDialog()
            }.onCompletion {
                dismissLoadingDialog()
            }.collect {
                resultCallback(it)
            }
        }
    }
}